﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "GbmpCommandBase.h"

#include "DrawNewLevelAction.h"
#include "StructureCmdIds.h"
#include "GmUiStructureCommandRegister.h"
#include "GbmpBuiltInCategoryUniIdentitiesNew.h"
#include "IBuilding.h"
#include "ILevel.h"
#include "BuildingUtils.h"
#include "IGbmpPlanView.h"
#include "StoreyManagementDlg.h"

#include "IDocument.h"
#include "IElementBasicInformation.h"

#include "IUiDocumentViewManager.h"

#include "Vector3dUtils.h"
#include "IPresetParameterManager.h"
#include "IGenericType.h"
#include "IUiDocument.h"
#include "IUserTransaction.h"
#include "IGenericElement.h"
#include "CmdStatusUtils.h"
#include "GbmpDocUtils.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;
using namespace std;

//////////////////////////////////////////////////////////////////////////
class CmdManageStorey : public GbmpCommandBase
{
public:
    CmdManageStorey():GbmpCommandBase(ID_CMD_MANAGE_STOREY){};
    ~CmdManageStorey(){};

public:
    virtual bool IsVisible() const override { return true; }
    virtual bool IsEnabled() const override;
    virtual OwnerPtr<IAction> ExecuteCommand(const gcmp::CommandParameters& cmdParams) override;
};

bool CmdManageStorey::IsEnabled() const
{
    return CmdStatusUtils::IsInDocumentEnvironment();
}

void CreateAssociateModelView(IDocument* pDoc, ILevel* pLevel)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc && pLevel, L"输入参数为空",L"GDMPLab",L"2024-03-30");

    IElementBasicInformation *pBasicInformation = pLevel->GetOwnerElement()->GetBasicInformation();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pBasicInformation, L"无效pBasicInformation",L"GDMPLab",L"2024-03-30");

    //创建关联平面视图
    //{
    //    // 创建对应的天花板视图
    //    GbmpModelViewUtil::CreateCeilingView(pDoc, pBasicInformation->GetName(), pLevel);
    //}

    {
        // 创建对应的平面视图
        GbmpPlanViewInput input;
        input.Document = pDoc;
        input.Name = pBasicInformation->GetName();
        input.Level = pLevel;
        IGbmpPlanView::Create(input);
    }
}

OwnerPtr<IAction> CmdManageStorey::ExecuteCommand(const gcmp::CommandParameters& cmdParams)
{
    IUiDocumentViewManager* pUiDocViewMgr = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUiDocViewMgr, L"pUiDocViewMgr为空",L"GDMPLab",L"2024-03-30");
    IDocument* pDoc = pUiDocViewMgr->GetCurrentUiDocument()->GetDbDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"文档为空",L"GDMPLab",L"2024-03-30");

    ElementId typeId;
    std::vector<IElement*> pElements = gcmp::GbmpDocUtils::GetElementsByCategory(pDoc, BuiltInCategoryUniIdentities::BICU_NEW_LEVEL_TYPE);
    FOR_EACH(pElement, pElements)
    {
        if (IGenericType* pType = quick_cast<IGenericType>(pElement))
        {
            typeId = pType->GetElementId();
            break;
        }
    }
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(typeId.IsValid(), L"标高类型不存在",L"GDMPLab",L"2024-03-30");

    StoreyManagementDlg dlg(pDoc);
    if (dlg.exec() != QDialog::Accepted)
    {
        return nullptr;
    }

    OwnerPtr<IUserTransaction> opUt = IUserTransaction::Create(pDoc, L"楼层管理");
    const std::vector<BuildingStruct>& buildings = dlg.GetBuildings();
    FOR_EACH(building, buildings)
    {
        // 新加的building
        if (building.buildingId.IsValid() == false)
        {
            IBuilding* pBuilding = IBuilding::Create(pDoc, building.name);
            DBG_WARN_AND_CONTINUE_UNLESS(pBuilding, L"创建IBuilding失败",L"GDMPLab",L"2024-03-30");
            ElementId buildingId = pBuilding->GetOwnerElement()->GetElementId();

            FOR_EACH(storey, building.storeyList.GetStoryList())
            {
                double elevation = building.storeyList.GetElevation(storey);
                ILevel* pLevel = ILevel::Create(pDoc, typeId, storey.name,
                    Vector3d(-20000.0, 0, elevation),
                    Vector3d(20000.0, 0, elevation),
                    Vector3d::UnitY,
                    buildingId
                );
                CreateAssociateModelView(pDoc, pLevel);
            }
        }
        else // 修改的building
        {
            IBuilding* pBuilding = BuildingUtils::GetBuildingById(pDoc, building.buildingId);
            DBG_WARN_AND_CONTINUE_UNLESS(pBuilding, L"获取IBuilding失败",L"GDMPLab",L"2024-03-30");
            ElementId buildingId = pBuilding->GetOwnerElement()->GetElementId();
            // 更新名字如果改过了
            if (pBuilding->GetOwnerElement()->GetBasicInformation()->GetName() != building.name)
            {
                pBuilding->GetOwnerElement()->GetBasicInformation()->SetName(building.name);
            }

            FOR_EACH(storey, building.storeyList.GetStoryList())
            {
                double elevation = building.storeyList.GetElevation(storey);
                // 新加的Level
                if (storey.levelId.IsValid() == false)
                {
                    ILevel* pLevel = ILevel::Create(pDoc, typeId, storey.name,
                        Vector3d(-20000.0, 0, elevation),
                        Vector3d(20000.0, 0, elevation),
                        Vector3d::UnitY,
                        buildingId
                    );
                    CreateAssociateModelView(pDoc, pLevel);
                }
                else // 修改的Level
                {
                    IGenericElement *pLevelElement = quick_cast<IGenericElement>(pDoc->GetElement(storey.levelId));
                    DBG_WARN_AND_CONTINUE_UNLESS(pLevelElement, L"指定Id的Level不存在",L"GDMPLab",L"2024-03-30");

                    ILevel* pLevel = quick_cast<ILevel>(pLevelElement->GetExternalObject());
                    DBG_WARN_AND_CONTINUE_UNLESS(pLevel, L"指定Id的Level不存在",L"GDMPLab",L"2024-03-30");

                    // 更新名字如果改过了
                    if (pLevel->GetOwnerElement()->GetBasicInformation()->GetName() != storey.name)
                    {
                        pLevel->GetOwnerElement()->GetBasicInformation()->SetName(storey.name);
                    }

                    // 更新标高值如果改过了
                    if (MathUtils::IsEqual(pLevel->GetElevation(), elevation) == false)
                    {
                        pLevel->SetElevation(elevation);
                    }
                }
            }
        }
    }

    // 删除单体
    pDoc->DeleteElements(dlg.GetDeletedBuildings());

    opUt->Commit();

    return nullptr;
}

REGISTER_GM_COMMAND(CmdManageStorey);
